﻿#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
/// <summary>
/// 编辑器工具类
/// </summary>
public partial class ESF_Utility
{
    #region ExecuteMenu 执行菜单
    /// <summary>
    /// Unity菜单映射
    /// </summary>
    static Dictionary<int, string> m_enESF_UnityMenuItem_Maping = typeof(enESF_UnityMenuItem).ESF_ValueToSpecialValue<int, ESF_AliasTooltipAttribute, string>((v, a) => { return a.alias; });
    /// <summary>
    /// 执行菜单
    /// </summary>
    /// <param name="_menu">菜单</param>
    public static void ExecuteMenuAssetsRefresh()
    {
        ExecuteMenu(enESF_UnityMenuItem.Assets_Refresh);
    }
    /// <summary>
    /// 执行菜单
    /// </summary>
    /// <param name="_menu">菜单</param>
    public static void ExecuteMenu(enESF_UnityMenuItem _menu)
    {
        EditorApplication.ExecuteMenuItem(m_enESF_UnityMenuItem_Maping[(int)_menu]);
    }
    #endregion

    #region PingObject
    /// <summary>
    /// PingObject
    /// </summary>
    /// <param name="_object">对象</param>
    /// <returns>PingObject</returns>
    public static UnityEngine.Object PingObject(UnityEngine.Object _object)
    {
        if (_object != null)
        {
            Selection.activeObject = _object;
            EditorGUIUtility.PingObject(_object);
        }        
        return _object;
    }

    /// <summary>
    /// PingObject
    /// </summary>
    /// <param name="_assetPath">资源路径</param>
    /// <returns>PingObject</returns>
    public static UnityEngine.Object PingObject(string _assetPath)
    {
        UnityEngine.Object obj = AssetDatabase.LoadMainAssetAtPath(_assetPath);
        PingObject(obj);
        return obj;
    }
    #endregion

    #region RevealInFinder
    /// <summary>
    /// RevealInFinder
    /// </summary>
    /// <param name="_object">对象</param>
    public static void RevealInFinder(UnityEngine.Object _object)
    {
        RevealInFinder(AssetDatabase.GetAssetPath(_object));
    }

    /// <summary>
    /// RevealInFinder
    /// </summary>
    /// <param name="_assetPath">资源路径</param>
    public static void RevealInFinder(string _assetPath)
    {
        EditorUtility.RevealInFinder(_assetPath);
    }
    #endregion

    #region CopyToClipboard 文本复制到剪帖板
    /// <summary>
    /// 文本复制到剪帖板
    /// </summary>
    /// <param name="_text">文本</param>
    public static void CopyToClipboard(string _text)
    {
        TextEditor te = new TextEditor();//很强大的文本工具
        te.text = _text;
        te.OnFocus();
        te.Copy();
    }
    #endregion

    #region IsSubToAssets Path是否从属于Assets路径内
    /// <summary>
    /// Path是否从属于Assets路径内
    /// </summary>
    /// <param name="_path">路径</param>
    /// <returns>True:是,False:否</returns>
    public static bool IsSubToAssets(string _path)
    {
        return IsSubTo(_path, globalAssetsFolderPath);
    }
    #endregion

    #region IsSubTo Path是否从属于Root路径
    /// <summary>
    /// Path是否从属于Root路径
    /// </summary>   
    /// <param name="_path">路径</param>
    /// <param name="_root">根路径</param>
    /// <returns>True:是,False:否</returns>
    public static bool IsSubTo(string _path, string _root)
    {
        string sub = GetSubTo(_path, _root);
        string rootName = Path.GetFileName(_root);
        bool isSub = sub.ESF_TransPathSeparatorCharToUnityChar().StartsWith(rootName);
        return isSub;
    }
    #endregion

    #region GetSubToAssets 获得Path相对于Assets目录
    /// <summary>
    /// 获得Path相对于Assets目录
    /// </summary>
    /// <param name="_path">路径</param>
    /// <returns>相对于Assets路径</returns>
    public static string GetSubToAssets(string _path)
    {
        return GetSubTo(_path, globalAssetsFolderPath);
    }
    #endregion

    #region GetSubTo 获得Path相对于Root的路径
    /// <summary>
    /// 获得Path相对于Root的路径
    /// </summary>
    /// <param name="_path">路径</param>
    /// <param name="_root">根目录</param>
    /// <returns>相对于Root的路径</returns>
    public static string GetSubTo(string _path, string _root)
    {
        Uri root = new Uri(Path.GetFullPath(_root));
        Uri com = new Uri(Path.GetFullPath(_path));
        string result = root.MakeRelativeUri(com).ToString().ESF_TransPathSeparatorCharToUnityChar();
        return result;
    }
    #endregion

    #region SubToFilePath 获得相对于FilePath路径的路径
    /// <summary>
    /// 获得相对于FilePath路径的路径
    /// </summary>
    /// <param name="_relaviveFilePath">相对FilePath文件路径</param>
    /// <param name="_filePath">文件路径</param>
    /// <returns>相对于Root的路径</returns>
    public static string SubToFilePath(string _relaviveFilePath, string _filePath)
    {
        return TrySubToAssets(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(_filePath), _relaviveFilePath)).ESF_TransPathSeparatorCharToUnityChar());
    }
    #endregion

    #region TrySubToAssets 尝试获得Path相对于Assets的路径
    /// <summary>
    /// 尝试获得Path相对于Assets的路径
    /// </summary>
    /// <returns>相对于Assets路径</returns>
    public static string TrySubToAssets()
    {
        return TrySubToAssets(string.Empty);
    }
    /// <summary>
    /// 尝试获得Path相对于Assets的路径
    /// </summary>
    /// <param name="_path">尝试的路径</param>
    /// <returns>相对于Assets路径</returns>
    public static string TrySubToAssets(string _path)
    {
        if (string.IsNullOrEmpty(_path))
        {//如果为空，则直接转到Assets路径下
            _path = globalAssetsFolderPath;
        }
        else if (IsSubToAssets(_path))
        {//如果是工程子目录
            _path = GetSubToAssets(_path);
        }
        return _path;
    }
    #endregion

    #region GetNearEditorRelativePath 获得最近的Editor相对路径
    /// <summary>
    /// Editor名称
    /// </summary>
    readonly static string mEditorName = "editor";
    /// <summary>
    /// 获得最近的Editor相对路径
    /// </summary>
    /// <param name="_path">路径</param>
    /// <returns>最近的Editor相对路径</returns>
    public static string GetNearEditorRelativePath(string _path)
    {
        List<string> result = new List<string>();
        if (File.Exists(_path))
        {
            _path = Path.GetDirectoryName(_path);
        }
        if (Directory.Exists(_path))
        {
            DirectoryInfo dir = new DirectoryInfo(_path);
            do
            {
                if (dir != null)
                {
                    if (dir.Name.ToLower().Equals(mEditorName.ToLower()))
                    {
                        break;
                    }
                    else
                    {
                        result.Add(enESF_SeparatorSymbol.DoubleDotBackSlash.ESF_FirstAttribute<ESF_AliasTooltipAttribute>().alias);
                    }
                }
                dir = dir.Parent;
            }
            while (dir != null);
        }
        else
        {
            ESF_P.ESF_Log($"路径：{_path} 不是有效路径");
        }
        return result.ESF_Join(enESF_SeparatorSymbol.Empty);
    }
    #endregion

    #region HasBelongEditorDirectory
    /// <summary>
    /// 是否包含Editor目录映射
    /// </summary>
    static Dictionary<int, bool> mHasBelongEditorDirectoryMaping = new Dictionary<int, bool>();
    /// <summary>
    /// 是否包含Editor目录
    /// </summary>
    /// <param name="_path">路径</param>
    /// <returns>true:包含,false:不包含</returns>
    public static bool HasBelongEditorDirectory(string _path)
    {
        bool result = false;
        _path = _path.ESF_TransPathSeparatorCharToUnityChar().ToLower();
        int key = _path.GetHashCode();
        if (!mHasBelongEditorDirectoryMaping.TryGetValue(key, out result))
        {
            string[] strs = _path.ESF_TransPathSeparatorCharToUnityChar().ToLower().ESF_Split(enESF_SeparatorSymbol.BackSlash);
            if (strs != null)
            {
                List<string> values = strs.ToList();
                result = values.Contains(mEditorName.ToLower());
            }
            mHasBelongEditorDirectoryMaping.Add(key, result);
        }       
        return result;
    }
    #endregion

    #region IsIllegalFile 是否是不合法的文件
    /// <summary>
    /// 非法Unity资源名称
    /// </summary>
    const string mIllegalUnityAssetName = @"[^\w\d_\-\.]";
    /// <summary>
    /// 是否是不合法的文件
    /// </summary>
    /// <param name="_name">文件名称</param>
    /// <returns>true:非法文件,false:合法文件</returns>
    public static bool IsIllegalFile(string _name)
    {
        return Regex.IsMatch(_name, mIllegalUnityAssetName);
    }
    #endregion

    #region IsIllegalDirectory 是否是不合法的目录
    /// <summary>
    /// 非法的目录
    /// </summary>
    const string mIllegalUnityDirectory = @"[^\w/\\\d_\-]";
    /// <summary>
    /// 是否是不合法的目录
    /// </summary>
    /// <param name="_directory">目录</param>
    /// <returns>true:非法目录,false:合法目录</returns>
    public static bool IsIllegalDirectory(string _directory)
    {
        return Regex.IsMatch(_directory, mIllegalUnityDirectory);
    }
    #endregion

    #region GetNearEditorFullPath 获得最近的Editor绝对路径
    /// <summary>
    /// 获得最近的Editor绝对路径
    /// </summary>
    /// <param name="_path">路径</param>
    /// <returns>最近的Editor相对路径</returns>
    public static string GetNearEditorFullPath(string _path)
    {
        string result = string.Empty;
        if (File.Exists(_path))
        {
            _path = Path.GetDirectoryName(_path);
        }
        if (Directory.Exists(_path))
        {
            DirectoryInfo dir = new DirectoryInfo(_path);
            do
            {
                if (dir != null)
                {
                    if (dir.Name.ToLower().Equals(mEditorName.ToLower()))
                    {
                        result = dir.FullName;
                        break;
                    }
                }
                dir = dir.Parent;
            }
            while (dir != null);
        }
        else
        {
            ESF_P.ESF_Log($"路径：{_path} 不是有效路径");
        }
        return result;
    }
    #endregion

    #region GetFullPath 获得FullPath
    /// <summary>
    /// 获得指定路径的FullPath
    /// </summary>
    /// <param name="_path">路径</param>
    /// <returns>FullPath</returns>
    public static string GetFullPath(string _path)
    {
        return Path.GetFullPath(TrySubToAssets(_path));
    }
    #endregion

    #region IsExecuteMethodInCmd 是否在Cmd中执行方法
    //https://docs.unity3d.com/Manual/CommandLineArguments.html
    /// <summary>
    /// 是否在Cmd中执行方法
    /// </summary>
    /// <returns>true:是,false:否</returns>
    public static bool IsExecuteMethodInCmd()
    {
        string[] clas = Environment.GetCommandLineArgs();
        List<string> args = new List<string>() { "-quit", "-batchmode", "-executeMethod" };
        if (clas != null && clas.Length > 0)
        {
            foreach (string s in clas)
            {
                if (args.Contains(s))
                {
                    args.Remove(s);
                }
            }
        }
        return args.Count <= 0;
    }
    #endregion

    #region DisplayDialog 显示对话框
    /// <summary>
    /// 显示Error对话框
    /// </summary>
    /// <param name="_message">信息</param>
    /// <returns>true:OK,false:otherwise</returns>
    public static bool DisplayDialogError(string _message)
    {
        return DisplayDialog("Dialog", _message, enESF_DisplayDialogType.Error);
    }

    /// <summary>
    /// 显示OK对话框
    /// </summary>
    /// <param name="_title">标题</param>
    /// <param name="_message">信息</param>
    /// <returns>true:OK,false:otherwise</returns>
    public static bool DisplayDialogError(string _title, string _message)
    {
        return DisplayDialog(_title, _message, enESF_DisplayDialogType.Error);
    }

    /// <summary>
    /// 显示OK对话框
    /// </summary>
    /// <param name="_message">信息</param>
    /// <returns>true:OK,false:otherwise</returns>
    public static bool DisplayDialogOK(string _message)
    {
        return DisplayDialog("Dialog", _message, enESF_DisplayDialogType.OK);
    }

    /// <summary>
    /// 显示OK对话框
    /// </summary>
    /// <param name="_title">标题</param>
    /// <param name="_message">信息</param>
    /// <returns>true:OK,false:otherwise</returns>
    public static bool DisplayDialogOK(string _title, string _message)
    {
        return DisplayDialog(_title, _message, enESF_DisplayDialogType.OK);
    }

    /// <summary>
    /// 显示OKCancel对话框
    /// </summary>
    /// <param name="_title">标题</param>
    /// <param name="_message">信息</param>
    /// <returns>true:OK,false:otherwise</returns>
    public static bool DisplayDialogOKCancel(string _title, string _message)
    {
        return DisplayDialog(_title, _message, enESF_DisplayDialogType.OK | enESF_DisplayDialogType.Cancel);
    }

    /// <summary>
    /// 显示对话框
    /// </summary>
    /// <param name="_title">标题</param>
    /// <param name="_message">信息</param>
    /// <param name="_type">类别</param>
    /// <returns>true:OK,false:otherwise</returns>
    public static bool DisplayDialog(string _title, string _message, enESF_DisplayDialogType _type)
    {
        bool result = false;
        enESF_DisplayDialogType okcancel = enESF_DisplayDialogType.OK | enESF_DisplayDialogType.Cancel;
        enESF_DisplayDialogType ok = enESF_DisplayDialogType.OK;
        enESF_DisplayDialogType error = enESF_DisplayDialogType.Error;
        if ((_type & okcancel) == okcancel)
        {
            result = EditorUtility.DisplayDialog(_title, _message, "OK", "Cancel");
        }
        else if ((_type & ok) == ok)
        {
            result = EditorUtility.DisplayDialog(_title, _message, "OK");
        }
        else if ((_type & error) == error)
        {
            result = EditorUtility.DisplayDialog(_title, _message, "Error");
        }
        return result;
    }
    #endregion

    #region DrawSeparator 绘制分隔线
    /// <summary>
    /// 绘制分隔线
    /// </summary>
    public static void DrawSeparator()
    {
        GUILayout.HorizontalSlider(1, 0, 1, GUILayout.Height(1));
        EditorGUILayout.Separator();
        EditorGUILayout.Separator();
    }
    #endregion

    #region DrawHorizontalLine
    /// <summary>
    /// 绘制横线
    /// </summary>
    public static void DrawHorizontalLine()
    {
        GUILayout.HorizontalSlider(1, 0, 1, GUILayout.Height(1));
    }
    #endregion

    #region DrawSeparatorDouble 绘制双分隔线
    /// <summary>
    /// 绘制双分隔线
    /// </summary>
    public static void DrawSeparatorDouble()
    {
        GUILayout.HorizontalSlider(1, 0, 1, GUILayout.Height(1));
        GUILayout.HorizontalSlider(1, 0, 1, GUILayout.Height(1));
        EditorGUILayout.Separator();
        EditorGUILayout.Separator();
    }
    #endregion

    #region TransToAssetDatabasePath 将当前路径转换为AssetDatabase形式路径
    /// <summary>
    /// 将当前路径转换为AssetDatabase形式路径
    /// </summary>
    /// <param name="_path">当前路径</param>
    /// <returns>AssetDatabase形式路径</returns>
    public static string TransToAssetDatabase(string _path)
    {
        return GetSubToAssets(_path).ESF_TransPathSeparatorCharToUnityChar();
    }
    #endregion

    #region GetPath 获得指定文件路径
    /// <summary>
    /// 获得指定文件路径
    /// </summary>
    /// <param name="_fileNameWithoutExtension">文件名【不包含后缀】</param>
    /// <param name="_directory">目录</param>
    /// <param name="_ext">后缀</param>
    /// <returns>文件路径</returns>
    public static string GetPath(string _fileNameWithoutExtension, string _directory, enESF_UnityFileExt _ext)
    {
        ESF_FileExtAttribute attr = null;
        return GetPath(_fileNameWithoutExtension, _directory, _ext, out attr);
    }
    #endregion

    #region GetPath 获得指定文件路径
    /// <summary>
    /// 获得指定文件路径
    /// </summary>
    /// <param name="_fileNameWithoutExtension">文件名【不包含后缀】</param>
    /// <param name="_directory">目录</param>
    /// <param name="_ext">后缀</param>
    /// <param name="_extAttr">后缀属性</param>
    /// <returns>文件路径</returns>
    public static string GetPath(string _fileNameWithoutExtension, string _directory, enESF_UnityFileExt _ext, out ESF_FileExtAttribute _extAttr)
    {
        _extAttr = _ext.ESF_FirstAttribute<ESF_FileExtAttribute>();
        _directory = TrySubToAssets(_directory);
        return Path.Combine(_directory, _fileNameWithoutExtension + _extAttr.ext).ESF_TransPathSeparatorCharToUnityChar();
    }
    #endregion
}
#endif
